package cdu.xjj.service.impl;


import cdu.xjj.custom.CustomUserDetails;
import cdu.xjj.pojo.dto.UserAddDTO;
import cdu.xjj.pojo.dto.UserLoginDTO;
import cdu.xjj.pojo.dto.UserUpdateDTO;
import cdu.xjj.pojo.entity.basic.Clazz;
import cdu.xjj.pojo.entity.basic.School;
import cdu.xjj.pojo.entity.manage.User;
import cdu.xjj.pojo.vo.LoginVO;
import cdu.xjj.repository.basic.ClazzRepository;
import cdu.xjj.repository.basic.SchoolRepository;
import cdu.xjj.repository.manage.UserRepository;
import cdu.xjj.service.UserService;
import cdu.xjj.utils.JwtUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;

import static cdu.xjj.utils.BeanCopyUtils.getNullOrEmptyPropertyNames;

@Slf4j
@Service
@RequiredArgsConstructor
public class UserServiceImpl implements UserService {

    private final PasswordEncoder passwordEncoder;

    private final AuthenticationManager authenticationManager;

    private final UserRepository userRepository;

    private final SchoolRepository schoolRepository;

    private final ClazzRepository clazzRepository;

    /**
     * 新增用户方法
     *
     * @param userAddDTO 新增用户数据传输对象
     */
    @Override
    public void save(UserAddDTO userAddDTO) {
        String encodePassword = passwordEncoder.encode(userAddDTO.getPassword());
        User user = new User();
        user.setUsername(userAddDTO.getUsername());
        user.setPassword(encodePassword);
        userRepository.save(user);
    }

    /**
     * 登录方法
     *
     * @param userLoginDTO 用户登录DTO
     */
    @Override
    public LoginVO login(UserLoginDTO userLoginDTO) {
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userLoginDTO.getUsername(), userLoginDTO.getPassword());
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);
        Assert.notNull(authenticate, "用户名或密码错误");

        // 获取用户详情
        CustomUserDetails customUserDetails = (CustomUserDetails) authenticate.getPrincipal();
        log.info("获取到用户详情 ：{}", customUserDetails);

        // 生成令牌并返回
        Map<String, Object> claims = new ConcurrentHashMap<>();
        claims.put("userId", customUserDetails.getUser().getId());
        claims.put("userName", customUserDetails.getUser().getUsername());
        claims.put("authorities", customUserDetails.getAuthorities());
        String token = JwtUtils.generateToken(claims);

        // 构造登录VO
        LoginVO loginVO = new LoginVO();
        BeanUtils.copyProperties(customUserDetails.getUser(), loginVO);
        loginVO.setToken(token);
        String role = customUserDetails.getUser().getRoles().get(0).getName();
        if (role.equals("EDU_BUR_ADMINISTRATOR")) {
            // 教育局管理员
            loginVO.setRole(2);
        } else if (role.equals("SCHOOL_ADMINISTRATOR")) {
            loginVO.setRole(1);
            // 查询学校详情
            Optional<School> opt = schoolRepository.findById(customUserDetails.getUser().getSchoolId());
            opt.ifPresent(school -> loginVO.setSchoolName(school.getName()));
        } else {
            loginVO.setRole(0);
            // 查询学校详情
            Optional<School> schoolOpt = schoolRepository.findById(customUserDetails.getUser().getSchoolId());
            schoolOpt.ifPresent(school -> loginVO.setSchoolName(school.getName()));
            // 查询班级详情
            Optional<Clazz> clazzOpt = clazzRepository.findById(customUserDetails.getUser().getClassId());
            clazzOpt.ifPresent(clazz -> {
                loginVO.setClassVal(clazz.getNum());       // 几班
                loginVO.setGrade(Integer.valueOf(clazz.getGrade()));  // 设置年级
            });
        }


        return loginVO;
    }

    /**
     * 修改用户信息
     *
     * @param userUpdateDTO 更新用户信息数据传输对象
     */
    @Override
    @Transactional
    public void updateUserInfo(UserUpdateDTO userUpdateDTO) {
          // 先根据id查询出用户详情
        Optional<User> opt = userRepository.findById(userUpdateDTO.getId());
        if(opt.isPresent()){
            User user = opt.get();
            BeanUtils.copyProperties(userUpdateDTO,user,getNullOrEmptyPropertyNames(userUpdateDTO));
            userRepository.save(user);
        }

    }






}
